package com.shiro;

import com.entity.RbacManager;
import com.service.RbacManagerService;
import com.service.RbacPermService;
import com.service.RbacRoleService;
import com.utils.JWTUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.RedisTemplate;

import java.util.Set;

/**
 * 自定义Realm域对象
 *
 * @author liuyukai
 * @date 2022/04/17
 */
@Configuration
public class MyRealm extends AuthorizingRealm {
    @Autowired
    RbacManagerService rbacManagerService;
    @Autowired
    RbacRoleService rbacRoleService;
    @Autowired
    RbacPermService rbacPermService;

    @Autowired
    RedisTemplate redisTemplate;
    /**
     * shiro底层判断子类逻辑有bug，因此重写此方法
     *
     * @param token 令牌
     * @return boolean
     */
    @Override
    public boolean supports(AuthenticationToken token) {
        return token instanceof WebToken;
    }

    /**
     * 获取授权信息
     *
     * @param principals JWT的token
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        String token = principals.getPrimaryPrincipal()+"";
        String username = JWTUtils.getUsername(token);
        String role = rbacRoleService.findByAccount(username);
//        Set<String> perms = rbacPermService.findByAccount(username);
        Set<String> perms =(Set<String>) redisTemplate.opsForHash().get("rbacPerm",username);
        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
        authorizationInfo.addRole(role);
        authorizationInfo.setStringPermissions(perms);
        return authorizationInfo;
    }
    /**
     * 获取认证信息
     *
     * @param jwtToken JWT的token
     * @return org.apache.shiro.authc.AuthenticationInfo
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken jwtToken) throws AuthenticationException {
        String token = jwtToken.getPrincipal()+"";
        String username = JWTUtils.getUsername(token);
        if("".equals(username)){
            throw new AuthenticationException("用户信息错误");
        }
        RbacManager manager =(RbacManager) redisTemplate.opsForHash().get("rbacManager",username);
        boolean verify = JWTUtils.verify(token, username, manager.getPassword());
        if(verify){
            return new SimpleAuthenticationInfo(token,token,"myRealm");
        }
        return null;
    }
}
